package com.wetao.testkotlin

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Button
import android.widget.TextView
import com.wetao.testkotlin.p1.paaaa
import java.io.File
import java.lang.Exception
import java.lang.IllegalArgumentException
import java.lang.IllegalStateException
import java.lang.StringBuilder

class MainActivity : AppCompatActivity() {
    val TAG = "MainActivity";
    //private var aa:String  //编译错误，必须要有初始值
    private lateinit var latevar:String  //可以编译，延迟初始化
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val i = "1"
        val j: Int
        j = 60;
        Log.i(TAG, i)
        val s1:String? = null
        val s2:String="aa"
        println("11-$s2!")
        println("22-${s2}3")
        Log.i(TAG, "33-$s2")
        if(s2 is String) {
            println(s2.toUpperCase())
        }
        bb(null)
        println(max(33, 44))
        val testc: TestC = TestC()
        testc.cc = 30
        println(testc.cc)
        val testd: TestD = TestD("ddddd")
        println(testd.dd)
        testd.dd = "2dd"
        println(testd.dd)
        val javaA: JavaA = JavaA()
        javaA.getA()
        val testE = TestE(11, 11)
        println(testE.isS)
        paaaa()
        println(TestF.BLU)
        println(TestG.RED)
        println(TestG.YELLOW.rgb())
        println(getColor(TestG.RED))
        println(getColor2(TestG.RED))
        if(testE is TestE) {
            println(testE.height)
        }
        for(t in 1..10) {
            println(t)
        }
        for(t in 1 until 10) {
            println(t)
        }
        for(t in 1 until 10 step 2) {
            println(t)
        }
        for(t in 10 downTo 1 step 2) {
            println(t)
        }
        for(t in 10 downTo 2 step 2) {
            println(t)
        }
        println(isLetter('a'))
        println(isNotDigit('a'))
        try {
            throw IllegalArgumentException("异常")
        }catch (e: Exception) {
            e.printStackTrace()
        }finally {
            println("finally")
        }
        val set = hashSetOf<Int>(1, 7, 53)
        val list = arrayListOf<Int>(2, 3, 4)
        val map = hashMapOf(1 to "one", 7 to "seven", 53 to "fifty-three")
        println(set.javaClass)
        println(list.javaClass)
        println(map.javaClass)
        println(list.last())
        println(set.min())
        println(list)
        println(list.joinToString(";", "(", ")"))
        println(list.joinToString(separator = "-", prefix = "<", postfix = ">"))
        println(list.joinToString())
        println(F_A)
        println("Kotlin".lastChar())
        val view: View = findViewById(R.id.btn_1)
        view.showOff()
        println("Tok".lastC)
        var sb = StringBuilder("otc")
        sb.lastC = 'B'
        println(sb)
        vara(1);
        val map2 = mapOf(1 to "one")
        val map3 = mapOf(2.to("two"))
        val (number, name) = 3 tt "three"
        println("number: ${number}; name:${name}")
        println("12.345-6.A".split("\\.|-".toRegex()))
        println("12.345-6.A".split(".", "-"))
        parsePath("mnt/sdcard/Android/data/com.wetao.flexiblerichtextview/files/flex/0034A96AD533B9159C34E4FFD5C94990.jpg")
        val kotlinLogo = """ |//
            .|b
            .|ccc\\
        """.trimMargin(".")
        println(kotlinLogo)
        TestH().click()
        TestH().showOff()
        TestI().showOff()

        val testUser1:TestUser1 = TestUser1("陈1")
        println(testUser1.nickname)
        val testUser2:TestUser2 = TestUser2("陈2")
        testUser2.nicename = "陈22"
        println(testUser2.nicename)
        val testUser3 = TestUser3("陈3")
        println(testUser3.nickname)
        val testUser4 = TestUser4("陈4")
        println(testUser4.nickname)
        val testUser6 = TestUser6("陈6")
        println(testUser6.nickname)
        val testUser7 = TestUser7("陈7")
        println(testUser7.nickname)
        val testUser9 = TestUser9();


        val testInterPrivate = TestInterPrivate("陈 TestInter1")
        println(testInterPrivate.nickname)
        val testInterSubscri = TestInterSubscri("陈 inter2")
        println(testInterSubscri.nickname)
        val testInterFace = TestInterFace("陈inter3")
        println(testInterFace.nickname)

        val testField = TestField("aa")
        testField.address = "陈 field"
        println(testField.address)
        val testLengthCounter = TestLenthCounter()
        testLengthCounter.addWord("hahaw")
        println(testLengthCounter.counter)

        val testClient = TestClient("chenyihong", 30)
        val testClient2 = TestClient("chenyihong", 30)
        println(testClient)
        println(testClient.equals(testClient2)) //true
        println(testClient == testClient2) //true
        println(testClient === testClient2) //false
        val testClientSet = hashSetOf<TestClient>(TestClient("chen", 30))
        println(testClientSet.contains(TestClient("chen", 30)))

        val testClientdata =  TestClentData("chenyihong", 30)
        val testClientdata2 = TestClentData("chenyihong", 30)
        println(testClientdata)
        println(testClientdata.equals(testClientdata2)) //true
        println(testClientdata == testClientdata2) //true
        println(testClientdata === testClientdata2) //false
        val testClientSetdata = hashSetOf<TestClentData>(TestClentData("chen", 30))
        println(testClientSetdata.contains(TestClentData("chen", 30)))

        TestObject.oInt.add("单例1")
        TestObject.oInt.add("单例2")
        TestObject.callFor()
        println(TestObject2.compare(File("/bb"), File("/cc")))
        val files = listOf<File>(File("/Z"), File("/a"))
        println(files.sortedWith(TestObject2))
        val testObject3 = listOf<TestObject3>(TestObject3("bob"), TestObject3("alice"))
        println(testObject3.sortedWith(TestObject3.TestObject4))
        TestObject5.bar()
        val testObject6 = TestObject6.newTestObject6("伴生对象可以访问私有构造函数")
        println(testObject6.nickname)
        val testObject7 = TestObject7.TestObject8.call("有名字的伴生对象")
        println(testObject7.nickname)
        println(TestObject10.call("伴生类可以继承接口"))
        val btn_2 = findViewById<Button>(R.id.btn_2)
        var tt = 1;
        btn_2.setOnClickListener(object:View.OnClickListener{
            override fun onClick(v: View?) {
                println("object 也可以表示匿名内部类")
                tt++;//访问外部变量的时候不需要final
            }
        })
        val olister = object : View.OnClickListener{
            override fun onClick(v: View?) {
                println("object 匿名内部类 单独")
            }
        }
        val btn_3 = findViewById<Button>(R.id.btn_3)
        btn_3.setOnClickListener(olister)
        val btn_4 = findViewById<Button>(R.id.btn_4)
        btn_4.setOnClickListener({
            println("lambda简化匿名内部类")
        })


        val tList = listOf<TestLambda>(TestLambda("alice", 29), TestLambda("bob", 31), TestLambda("carol", 31))
        findTheOldest(tList)
        println(tList.maxBy { it.age })
        println(tList.maxBy(TestLambda::age))
        val sum = {x:Int, y:Int -> x + y} //lambda表达式，是一个函数
        println(sum(1, 2));
        { println(42)}()
        run{ println(55)}
        tList.maxBy ({p:TestLambda -> p.age}) //标准语法
        tList.maxBy (){ p:TestLambda -> p.age } //lambda是最后一个实参适用
        tList.maxBy { p:TestLambda -> p.age } //lambda是唯一一个实参适用
        tList.maxBy { p -> p.age } //推导出参数
        tList.maxBy { it.age } //只有一个参数是，分配默认参数it
        val getAge = {p:TestLambda -> p.age}
        val getAge2 = TestLambda::age //意思和上面一句一样
        tList.maxBy(getAge)
        tList.maxBy(getAge2)
        val names1 = tList.joinToString(separator = " ",
            transform = {p -> p.name})
        println(names1)
        val names2 = tList.joinToString(" "){p -> p.name}
        println(names2)
        val sum2 = { x:Int, y:Int ->
            println("最后一个表达式是lambda返回的接口")
            x + y
        }
        println(sum2(2,3))
        run(::salute) //引用顶层函数的lambda
        val createT = ::TestLambda //lambda构造函数
        val ct2 = createT("cyh", 28)
        println(ct2)
        val list3 = listOf<Int>(1, 2, 3, 4)
        println(list3.filter { it % 2 == 0 })
        println(tList.filter { it.age > 30 })
        println(list3.map { it * it })
        println(tList.map{it.name})
        val canBeInClub27 = {p:TestLambda -> p.age <= 30}
        println(tList.all(canBeInClub27)) //是否所有元素都满足条件
        println(tList.any(canBeInClub27)) //至少存在一个满足条件
        println(tList.count(canBeInClub27)) //符合条件的个数
        println(tList.find(canBeInClub27)) //返回第一个符合条件的或者null
        println(tList.groupBy{it.age}) //分组返回map<int, list>
        val list4 = listOf<String>("acc", "ab", "cdf")
        println(list4.groupBy(String::first)) //按首字母分组
        println(list4.flatMap { it.toList() }) //对每个元素进行变换，再合成一个列表
        println(tList.map(TestLambda::name).filter{ it.startsWith("a")}) //中间会产生两个临时列表
        println(tList.asSequence().map(TestLambda::name).filter { it.startsWith("a") }.toList()) //列表转序列，支持集合一样的api,中间不会产生临时列表，最后转换成列表
        //集合和序列执行顺序不一样，集合是所有数据调用第一个转换和在调用第二个转换,而序列是第一个数据调用第一个转换在调用第二个转换，以此类推
        println(listOf(1, 2, 3, 4).asSequence().map { println("map1($it) ");it*it}.filter { println("filter1($it) "); it % 2 == 0 }) //不会有打印， 惰性的，没有调用toList()
        println(listOf(1, 2, 3, 4).asSequence().map { println("map2($it) ");it*it}.filter { println("filter2($it) "); it % 2 == 0 }.toList()) //有打印
        println(listOf(1, 2, 3, 4).map { println("map3($it) ");it*it}.filter { println("filter3($it) "); it % 2 == 0 }.toList())
        val naturalNumbers = generateSequence(0) { it + 1 }
        val numbersTo100 = naturalNumbers.takeWhile { it <= 100 }
        println(numbersTo100.sum())
        println(alphabet1());
        println(alphabet2());
        println(alphabet3());
        val tv_1:TextView = findViewById(R.id.tv_1);
        tv_1.apply {
            text = "测试 apply"
            textSize = 20f
        }




        //strLen(null) //编译不过去
        println(strLenSafe("aa"))
        println(strLenSafe(null))
        val x_null:String? = null
        //var y_null:String = x_null; //编译错误
        var y_null:String = ""
        var z_null:String? = y_null
        //strLen(z_null) //编译错误
        printAllCps("abc")
        printAllCps(null)
        println(foo("不是空"))
        println(foo(null))
        println(strLenSafe2("abc"))
        println(strLenSafe2(null))
        println(strIs("abc")) //true
        println(strIs(null))  //false
        println(strAs("abc"))
        println(strAs(null))
        //ignoreNulls(null)  //报异常
        ignoreNulls("abc")
        var email: String? = "yole@example.com"
        email?.let { sendEmailTo(it) }  //let不为null才执行大括号里面的语句，常用于可null传非null
        email = null
        email?.let{ sendEmailTo(it) }
        val sNull:String? = null
        println(sNull.isNullOrBlank()) //true
        println(sNull.isNullOrBlank2()) //true
        printHashCode(null)
        //printHashCode2(null) //编译错误

        val t_i : Int = 1
        //val t_l : Long = t_i //编译错误
        var t_l : Long = t_i.toLong()
        val t_a : Any = 26 //根类型
        //val t_b : Any = null //报错
        val t_c : Any? = null

        //下面四个可空性是不一样的
        val n_list_1 = ArrayList<Int>()
        val n_list_2 = ArrayList<Int?>()
        val n_list_3:ArrayList<Int>? = ArrayList<Int>()
        val n_list_4:ArrayList<Int?>? = ArrayList<Int?>()

        val source: Collection<Int> = arrayListOf(3, 5, 7) //不可变集合
        val target: MutableCollection<Int> = arrayListOf(1) //可变集合
        copyElements(source, target)
        println(target)

        //List 只读listOf ->可变mutableListOf、arrayListOf
        //Set 只读setOf ->可变mutableSetOf、hashSetOf、linkedSetOf、sortedSetOf
        //Map 只读mapOf ->可变mutableMapOf、hashMapOf、linkedMapOf、sortedMapOf

        val str_arr:Array<String> = arrayOf("11", "22", "33")
        for(i in str_arr.indices) {
            println("Argument $i is : ${str_arr[i]}")
        }
        val str_arr2 = Array<String>(26) {i -> ('a' + i).toString()}
        println(str_arr2.joinToString("*"))
        val str_list = listOf<String>("a", "b", "c")
        println("%s/%s/%s".format(*str_list.toTypedArray()))   //期望vararg（可变参数）时，使用展开运算符 * 传递给数组
        //Array<Int>() 装箱类数组
        //IntArry() 基本数据类数组


        val p1 = TestPoint(10, 20)
        val p2 = TestPoint(30, 40)
        println(p1 + p2)
        val p3 = TestPerson2("Alice", "Smith")
        val p4 = TestPerson2("Bob", "Johnson")
        println(p3 < p4)
        println(p1[0])
        println(p1[1])
        val rect = TestRectangle(p1, p2)
        println(TestPoint(30, 30) in rect)
        //结构声明
        val (name1, name2) = p3
        println(name1)
        println(name2)


        //高阶函数，以函数或者lambda作为参数或者返回值的函数叫高阶函数
        //函数类型
        val sum3 = { x:Int, y:Int -> x+y }
        val action3 = { println(42) }
        //相当于
        val sum4:(Int, Int) -> Int = {x, y -> x + y}
        val action4:() -> Unit = { println(42) } //返回类型Unit不能省略

        val canReturnNull: () -> Int? = { null } //返回值可null
        val funOrNull:((Int, Int) -> Int)? = null //函数类型可null
        twoAndThree{a, b -> a + b}
        twoAndThree{a, b -> a * b}

        //如果你在lambda中使用return关键字，它会从调用lambda的函数中返回，
        //并不只是从lambda中返回。这样的return语句叫做非局部返回，
        //因为它是从一个比包含return代码块更大的代码块中返回
        //也就是说，从有fun关键字的函数返回
        //如果只想从lambda中返回，需要设置标签, 花括号之前放一个标签如 lable@, 返回return@lable
        lookForAlice(arrayListOf("Alice"))
        lookForAlice2(arrayListOf("Alice"))
        println(StringBuilder().apply sb@{
            listOf<Int>(1, 3, 3).apply {
                this@sb.append(this.toString()) //两个this代表不同，一个外层，一个内层
            }
        })


        val list5 = listOf<Int>(1, 2, 3, 4)
        println(list5 is List<Int>) //true
        println(list5 is List<*>) //true



    }

    fun findTheOldest(p:List<TestLambda>) {
        var maxAge = 0
        var theOldest:TestLambda ?= null
        for(s in p) {
            if(s.age > maxAge) {
                maxAge = s.age
                theOldest = s
            }
        }
        println(maxAge)
        println(theOldest)
    }

    fun parsePath(path: String) {
        val directory = path.substringBeforeLast("/")
        val fullName = path.substringAfterLast("/")
        val fileName = fullName.substringBeforeLast(".")
        val extension = fullName.substringAfterLast(".")
        println("directory: $directory, fullName: $fullName, fileName: $fileName, extension: $extension")

        val a = path.substringBefore("/")
        val b = path.substringAfter("/")
        println("a: $a, b: $b")
    }
    infix fun Any.tt(other: Any) = Pair(this, other)

    fun vara(vararg arg: Int): Int{
        return arg.size
    }
    fun isLetter(c: Char) = c in 'a'..'z' || c in 'A'..'Z'
    fun isNotDigit(c: Char) = c !in '0'..'9'

    fun getColor(color: TestG) = when(color) {
        TestG.YELLOW -> "yw"
        TestG.RED -> "rd"
        else -> "el1"
    }
    fun getColor2(color: TestG) = when(color){
        TestG.RED, TestG.YELLOW -> "rw"
        else -> "el2"
    }
    fun getColor3(c1: TestG, c2: TestG) =
        when(setOf<TestG>(c1, c2)) {
            setOf(TestG.RED, TestG.GREEN) ->"rn"
            else -> "el3"
        }
    fun getColor4(c1: TestG, c2: TestG) =
        when{
            c1 == TestG.GREEN && c2 == TestG.RED -> "rd"
            else -> "el4"
        }

    //with第一个参数，作为第二参数的输入
    fun alphabet1() : String{
        val stringBuilder = StringBuilder()
        return with(stringBuilder) {
            for(letter in 'A'..'Z') {
                this.append(letter)
            }
            append("\n Now I know the alphabet!")
            this.toString()
        }
    }
    fun alphabet2() = with(StringBuilder()) {
        for(letter in 'A'..'Z') {
            this.append(letter)
        }
        append("\n Now I know the alphabet!")
        this.toString()
    }
    //apply 对象作为函数的输入
    fun alphabet3() = StringBuilder().apply {
        for(letter in 'a'..'z'){
            append(letter)
        }
        append("\n Now I know the alphabet!")
    }.toString()
    //带参数的lambda表达式
    fun alphabet4() = buildString {
        for(letter in '1'..'9') {
            append(letter)
        }
        append("\n Now I know the alphabet")
    }


    //传参不能为null
    fun strLen(s: String) = s.length
    //fun strLenSafe(s: String?) = s.length //编译错误
    fun strLenSafe(s:String?): Int =
        if(s != null) s.length else 0
    fun printAllCps(s:String?) {
        val allCaps:String? = s?.toUpperCase()
        println(allCaps)
    }
    fun foo(s:String?) : String{
        val t: String = s?:""
        return t
    }
    fun strLenSafe2(s:String?):Int = s?.length?:0
    fun strIs(s:String?):Boolean {
        if(s is String) {
            return true;
        }else {
            return false;
        }
    }
    fun strAs(s:String?):String = s as? String ?: "s不是String类型"
    fun ignoreNulls(s: String?) {
        val sNotNull : String = s!!  //!!表示判null断言，如果s为null，报异常，否则往下执行
        println(sNotNull.length)
    }
    fun sendEmailTo(email: String) {
        println("Sending email to $email")
    }

    fun <T> printHashCode(t:T) { //T是可以为null的，实际类型是 Any?
        println(t?.hashCode())
    }
    fun <T: Any> printHashCode2(t: T) {//t 不能为null
        println(t.hashCode())
    }
    fun fUnit() : Unit{  //没有返回类型

    }
    fun fUnit2() { //省略了Unit

    }
    fun fFail(message:String):Nothing{ //Nothing 指死循环或者抛异常，永远没有返回值
        throw IllegalStateException(message)
    }
    fun <T> copyElements(source: Collection<T>,
                         target: MutableCollection<T>) {
        for(item in source) {
            target.add(item)
        }
    }
    fun twoAndThree(operation:(Int, Int) -> Int) {
        val result = operation(2, 3)
        println("The result is $result")
    }
    fun lookForAlice(sList: List<String>) {
        sList.forEach label@{
            if(it == "Alice"){
                return@label
            }
        }
        println("这一行总是会被打印")
    }
    fun lookForAlice2(sList: List<String>) {
        sList.forEach{
            if(it == "Alice") {
                return@forEach
            }
            println("这一行总是会被打印2")
        }
    }

    fun lookForAlice3(sList: List<String>) {
        sList.forEach(fun(item){
            if(item == "Alice") return //从最后一个fun返回
        })
    }

    fun lookForAlice4(sList: List<String>) {
        sList.forEach {
            if(it == "Alice") return //从最后一个fun返回
        }
    }

    //相当于java的<T extends Nmber> T sum(List<T> list)
    fun <T: Number> List<T>.sum():T{
        return this[0]
    }

}
fun bb(t: Array<String>?) {
    println("hello word")
}
fun max(a: Int, b: Int) = if(a > b) a else b
fun String.firstChar():Char=this.get(0)
val String.lastC: Char
    get() = get(length - 1)
var StringBuilder.lastC: Char
    get() = get(length - 1)
    set(value: Char) {
        this.setCharAt(length - 1, value)
    }
fun View.showOff() = println("I am a view!")
fun Button.showOff() = println("I am a button!")
fun salute() = println("Salute")
fun String?.isNullOrBlank2():Boolean = this == null || this.isBlank() //null字符串也可以调用这一个函数，this可能为null
